/*
 * #%L
 * Alfresco Repository
 * %%
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 * %%
 * This file is part of the Alfresco software. 
 * If the software was purchased under a paid Alfresco license, the terms of 
 * the paid license agreement will prevail.  Otherwise, the software is 
 * provided under the following open source license terms:
 * 
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */
package org.alfresco.repo.search;

import java.util.Collection;

import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;

/**
 * This interface abstracts how indexing is used from within the node service implementation.
 * 
 * It has to optionally offer transactional integration For example, the lucene indexer
 * 
 * @author andyh
 */

public interface Indexer
{
    /**
     * Create an index entry when a new node is created. A node is always created with a name in a given parent and so a relationship ref is required.
     * 
     * @param relationshipRef
     *            ChildAssociationRef
     */
    public void createNode(ChildAssociationRef relationshipRef);

    /**
     * Update an index entry due to property changes on a node. There are no strucural impications from such a change.
     *
     * @param nodeRef
     *            NodeRef
     */
    public void updateNode(NodeRef nodeRef);

    /**
     * Delete a node entry from an index. This implies structural change. The node will be deleted from the index. This will also remove any remaining refernces to the node from the index. The index has no idea of the primary link.
     * 
     * @param relationshipRef
     *            ChildAssociationRef
     */
    public void deleteNode(ChildAssociationRef relationshipRef);

    /**
     * Create a refernce link between a parent and child. Implies only (potential) structural changes
     * 
     * @param relationshipRef
     *            ChildAssociationRef
     */
    public void createChildRelationship(ChildAssociationRef relationshipRef);

    /**
     * Alter the relationship between parent and child nodes in the index.
     * 
     * This can be used for:
     * <OL>
     * <LI>rename,
     * <LI>move,
     * <LI>move and rename,
     * <LI>replace
     * </OL>
     * 
     * This could be implemented as a delete and add but some implementations may be able to optimise this operation.
     * 
     * @param relationshipBeforeRef
     *            ChildAssociationRef
     * @param relationshipAfterRef
     *            ChildAssociationRef
     */
    public void updateChildRelationship(ChildAssociationRef relationshipBeforeRef, ChildAssociationRef relationshipAfterRef);

    /**
     * Delete a relationship between a parent and child.
     * 
     * This will remove a structural route through the index. The index has no idea of reference and primary relationships and will happily remove the primary relationship before refernces which could remain.
     * 
     * Use delete to ensure all strctural references are removed or call this sure you are doing an unlink (remove a hard link in the unix file system world).
     * 
     * @param relationshipRef
     *            ChildAssociationRef
     */
    public void deleteChildRelationship(ChildAssociationRef relationshipRef);

    /**
     * Does a database vs index comparison for the given created/updated/renamed/referenced nodeRef in order to determine the set of indexing operations required
     * 
     * @param nodeRef
     *            the nodeRef to process
     * @param searcher
     *            searcher to query the indexes
     * @param addedParents
     *            set to add new secondary parent associations to
     * @param deletedParents
     *            set to add removed secondary parent associations to
     * @param createdNodes
     *            set to add created nodes to
     * @param updatedNodes
     *            set to add updated nodes to
     */
    public void detectNodeChanges(NodeRef nodeRef, SearchService searcher,
            Collection<ChildAssociationRef> addedParents, Collection<ChildAssociationRef> deletedParents,
            Collection<ChildAssociationRef> createdNodes, Collection<NodeRef> updatedNodes);

    /**
     * Delete the index for a store
     * 
     * @param storeRef
     *            StoreRef
     */
    public void deleteIndex(StoreRef storeRef);

    public void flushPending();

    /**
     * Activates 'read through' behaviour for this indexer. Rather than accessing the database through the current (potentially old) transaction, it will use a discrete read only transaction for each node it indexes. This avoids 'stale' nodes building up in the caches during long reindex runs.
     * 
     * @param isReadThrough
     *            boolean
     */
    public void setReadThrough(boolean isReadThrough);
}
